﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace NMF.Languages.Adaption
{
    [DebuggerDisplay("{Name} : {Type.Name}")]
    public class AdaptiveProperty : IProperty, ICollectionProperty
    {
        private string name;
        private IType type;
        private AdaptiveClass declaringClass;

        public AdaptiveProperty(AdaptiveClass parent, string name)
        {
            this.declaringClass = parent;
            this.name = name;
        }

        public bool IsCollectionProperty { get { return isCollectionProperty; } }
        private bool isCollectionProperty;

        public System.Collections.IEnumerable GetItems(object source)
        {
            return GetValue(source) as IEnumerable;
        }

        public IType Type
        {
            get { return type; }
        }

        public void SetAPrioriType(IType type)
        {
            this.type = type;
        }

        public string Name
        {
            get { return name; }
        }

        public object GetValue(object source)
        {
            var instance = source as AdaptiveInstance;
            object value;
            if (instance.Values.TryGetValue(this, out value))
            {
                return value;
            }
            else
            {
                return null;
            }
        }

        public void SetValue(object source, object value)
        {
            var instance = source as AdaptiveInstance;
            if (instance.Values.ContainsKey(this))
            {
                instance.Values[this] = value;
            }
            else
            {
                instance.Values.Add(this, value);
            }
        }

        public void AddItem(object source, object value)
        {
            if (IsCollectionProperty)
            {
                var list = GetValue(source) as IList;
                if (list == null)
                {
                    list = new ArrayList();
                    SetValue(source, list);
                }
                list.Add(value);
            }
            else
            {
                throw new InvalidOperationException("no collection property");
            }
        }

        public IClass DeclaringClass
        {
            get { return declaringClass; }
        }

        public void AssertCollectionProperty(IType collectionType)
        {
            this.isCollectionProperty = true;
            this.type = collectionType;
        }

        public void AssertProperty(IType propertyType)
        {
            this.isCollectionProperty = false;
            this.type = propertyType;
        }

        public void InitializeDefaultValue(object source)
        {
            if (IsCollectionProperty)
            {
                SetValue(source, new ArrayList());
            }
        }

        public void AssertIsValidFor(IClass declaringClass)
        {
        }


        public bool IsReadOnly
        {
            get { return false; }
        }


        public void RemoveItem(object source, object value)
        {
            if (IsCollectionProperty)
            {
                var list = GetValue(source) as IList;
                if (list == null)
                {
                    list = new ArrayList();
                    SetValue(source, list);
                }
                list.Remove(value);
            }
            else
            {
                throw new InvalidOperationException("no collection property");
            }
        }
    }
}
